GetSQLSelectWhereById 是用來生成一個 SQL SELECT 語句中的 WHERE 條件語句,根據傳入的實體對象 entity 以及可選的 sqlWhere 字符串來動態生成 SQL 條件。讓我們逐行來解析這段代碼的每個部分。
如果 sqlWhere 是 "Price > 100",生成的語句會是:Price > 100 AND (。
如果 sqlWhere 是空的,生成的語句會是:WHERE (。
4. 添加主鍵條件
csharp
複製程式碼
str_command += $"{str_entity_name}.{str_key_name} = ";
str_command += $"@{str_key_name}) ";
{str_entity_name}.{str_key_name}:這段代碼動態生成實體的主鍵條件。str_entity_name 是實體對應的表名,str_key_name 是主鍵列的名稱。因此,這行代碼生成的是 表名.主鍵 的形式。
@{str_key_name}:@ 表示 SQL 語句中的參數佔位符,這裡會根據主鍵名稱生成一個 SQL 參數。例如,如果主鍵名稱是 ProductId,這段代碼會生成 @ProductId,這樣 SQL 語句在執行時可以使用參數化查詢來避免 SQL 注入。
):這個括號結束了 WHERE 條件中的主鍵判斷。
5. 返回結果
csharp
複製程式碼
return str_command;
這行代碼將生成的 SQL 語句返回。
總結這段代碼的邏輯
這段代碼的核心作用是動態生成一個 SQL 查詢的 WHERE 子句,它包括:
可選的條件 sqlWhere(如果有)。
主鍵的條件。
具體來說:
如果傳入的 sqlWhere 是非空的,它會將該條件放在 WHERE 子句的前面,並與主鍵條件通過 AND 連接。
如果 sqlWhere 是空的,它只生成主鍵條件。
具體示例
假設你有一個 Product 類,並且主鍵是 ProductId,當你傳入實體對象 Product 並且沒有提供 sqlWhere 時,生成的 SQL 語句會是:
sql
複製程式碼
WHERE (Product.ProductId = @ProductId)
如果你提供了 sqlWhere = "Price > 100",則生成的語句會是:
sql
複製程式碼
Price > 100 AND (Product.ProductId = @ProductId)
GetSQLUpdateCommand 和 GetSQLUpdateParameters,用於生成 SQL 更新語句及其對應的參數。讓我們逐步解釋每個方法的內容。
GetSQLUpdateCommand 方法
這個方法用來生成一個 SQL 更新命令,步驟如下:
初始化變數:
csharp
複製程式碼
string str_command = "";
string str_key_name = GetKeyColumnName(entity);
str_command:用來儲存生成的 SQL 更新語句。
str_key_name:取得該實體的主鍵欄位名稱。
檢查主鍵名稱是否有效:
csharp
複製程式碼
if (!string.IsNullOrEmpty(str_key_name))
如果主鍵名稱有效,則進入下一步。
初始化計數器和標誌:
csharp
複製程式碼
int int_count = 0;
bool bln_iskey = false;
bool bln_notmapped = false;
string str_entity_name = entity.GetType().Name;
string str_entity_full_name = entity.GetType().FullName;
str_command = $"UPDATE {str_entity_name} SET ";
int_count:用於計數,追蹤已處理的欄位數量。
bln_iskey:用於標記是否當前欄位是主鍵。
bln_notmapped:用於標記欄位是否被標記為不映射。
str_entity_name 和 str_entity_full_name 分別是實體的名稱和全名。
獲取屬性並生成 SQL 語句:
csharp
複製程式碼
var props = entity.GetType().GetProperties();
foreach (var prop in props)
{
bln_iskey = IsKeyAttribute(str_entity_name, prop.Name);
bln_notmapped = IsNotMappedAttribute(str_entity_full_name, prop.Name);
if (!bln_iskey && !bln_notmapped)
{
int_count++;
if (int_count > 1) str_command += ", ";
str_command += $"{prop.Name} = @{prop.Name} ";
}
}
這段代碼通過反射獲取實體的所有屬性,然後檢查每個屬性是否為主鍵或不映射。
如果屬性不是主鍵且未被標記為不映射,則將其加入到更新命令中。
附加 WHERE 子句:
csharp
複製程式碼
str_command += $"WHERE {str_key_name} = @{str_key_name}";
最後,附加一個 WHERE 子句,以確保只有指定主鍵的記錄會被更新。
GetSQLUpdateParameters 方法
這個方法用來生成 SQL 更新的參數,步驟如下:
初始化 DynamicParameters:
csharp
複製程式碼
DynamicParameters parm = new DynamicParameters();
string str_key_name = GetKeyColumnName(entity);
檢查主鍵名稱:
csharp
複製程式碼
if (!string.IsNullOrEmpty(str_key_name))
如果主鍵名稱有效,則進入下一步。
獲取屬性並添加參數:
csharp
複製程式碼
var props = entity.GetType().GetProperties();
foreach (var prop in props)
{
bln_notmapped = IsNotMappedAttribute(str_entity_full_name, prop.Name);
if (!bln_notmapped)
{
parm.Add(prop.Name, prop.GetValue(entity, null));
}
}
這段代碼通過反射獲取實體的所有屬性,並檢查每個屬性是否被標記為不映射。
如果屬性未被標記為不映射,則將其名稱和值添加到 DynamicParameters 中。
為什麼參數要另外用出來
將 SQL 更新命令和參數分開設計有幾個原因:
提高可讀性:將 SQL 語句和參數分開,使代碼更加清晰易懂,便於維護和調試。
防止 SQL 注入:使用參數化查詢(如 @{prop.Name})有助於防止 SQL 注入攻擊,因為它確保用戶提供的數據不會直接嵌入到 SQL 語句中。
方便重用:可以在不同的查詢中重用參數,尤其是在複雜的操作中,可以減少重複代碼。
簡化測試:將參數獨立出來,可以更容易地對 SQL 語句和參數進行單元測試,檢查其正確性。